package com.school.generator.controller;

import com.school.generator.base.GenericResponse;
import com.school.generator.entity.ColumnItem;
import com.school.generator.entity.TableItem;
import com.school.generator.repository.CodeRepository;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * @description:
 * @author: zhangyaoting
 * @date: 2019/07/03 22:00
 * @version: V1.0
 */
@Slf4j
@RestController
@RequestMapping("/code")
public class CodeController {
    private static final String TEMPLATE_PATH = "classpath:ftl";

    private Configuration configuration;

    @Autowired
    private CodeRepository codeRepository;

    /** 查看所有表 **/
    @GetMapping("/tables/{tableSchema}")
    public Callable<GenericResponse<TableItem>> tables(@PathVariable("tableSchema") String tableSchema) {
        return () -> GenericResponse.success(codeRepository.findTables(tableSchema));
    }

    /** 生成文件到目录 **/
    @PostMapping("/auto")
    public Callable<GenericResponse<ColumnItem>> autoFile(@RequestBody TableItem tableItem) {
        return () -> {
            tableItem.setColumns(codeRepository.findColumnByTable(tableItem.getTableName()));
            tableItem.init();
            Boolean result = autoFileTo(tableItem);
            return GenericResponse.success("0",result.toString(),tableItem);
        };
    }

    public Boolean autoFileTo(TableItem tableItem) {
        String xmlPath = tableItem.buildPath("/src/main/resources/repository/base");
        String repositoryPath = tableItem.buildPath("/src/main/java/%s/repository");
        String servicePath = tableItem.buildPath("/src/main/java/%s/service");
        String serviceImplPath = tableItem.buildPath("/src/main/java/%s/service/impl");
        String controllerPath = tableItem.buildPath("/src/main/java/%s/controller");
        String entityPath = tableItem.buildPath("/src/main/java/%s/entity");

        autoFileToPath(tableItem,"TEMP_MAPPER.ftl",xmlPath,"/%sRepositoryBase.xml", false);
        autoFileToPath(tableItem,"TEMP_REPOSITORY.ftl",repositoryPath,"/%sRepository.java", true);
        autoFileToPath(tableItem,"TEMP_SERVICE.ftl",servicePath,"/%sService.java", true);
        autoFileToPath(tableItem,"TEMP_SERVICEIMPL.ftl",serviceImplPath,"/%sServiceImpl.java", true);
        autoFileToPath(tableItem,"TEMP_CONTROLLER.ftl",controllerPath,"/%sController.java", true);
        autoFileToPath(tableItem,"TEMP_ENTITY.ftl",entityPath,"/%s.java", true);
        return true;
    }

    public Boolean autoFileToPath(TableItem tableItem, String temp, String path, String file, boolean isExist) {
        // step1 创建freeMarker配置实例
        if (configuration == null) {
            configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        }
        Writer writer = null;
        try {
            // step2 获取模版路径
            configuration.setDirectoryForTemplateLoading(ResourceUtils.getFile(TEMPLATE_PATH));
            // step4 加载模版文件
            Template template = configuration.getTemplate(temp);
            // step5 生成输出的文件夹
            File fileDir = new File(path);
            // step6 创建文件夹，不存在则创建
            if (!fileDir.exists()) {
                fileDir.mkdirs();
            }
            // step7 指定生成输出的文件
            String fileName = String.format(file, tableItem.getEntityName());
            File output = new File(fileDir + fileName);
            if(isExist && output.exists()){
                log.info("文件【{}】已存在", fileName);
                return true;
            }
            // step8 写入流
            writer = new FileWriter(output);
            // step9 输出文件
            template.process(tableItem, writer);
            log.info("生成文件 : {}", fileDir + fileName);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (null != writer) {
                    writer.flush();
                    writer.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return true;
    }

    /** 导出mybatis的xml文件 **/
    @GetMapping("/export")
    public Callable<GenericResponse<Object>> export(HttpServletResponse response) {
        return () -> {

            try {
                //要生成的文件名写在这里  只要文件名就行
                String fileName = "summary.xml";
                fileName = new String(fileName.getBytes("utf-8"), "ISO8859-1");
                response.setCharacterEncoding("utf-8");
                response.setContentType("multipart/form-data");
                response.setHeader("Content-disposition", "attachment; filename=" + fileName);

                // 获得输出流
                OutputStream os = response.getOutputStream();

                // 执行导出
                auto(os);

                // 关闭输出流。
                os.close();

            } catch (Exception e) {
                e.printStackTrace();
                return GenericResponse.success();
            }
            //  返回值要注意必须为null，要不然就出现下面这句错误！
            //  java+getOutputStream() has already been called for this response
            return null;
        };
    }

    public void auto(OutputStream os) {
        // step1 创建freeMarker配置实例
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        Writer out = null;
        try {
            // step2 获取模版路径
            configuration.setDirectoryForTemplateLoading(ResourceUtils.getFile(TEMPLATE_PATH));
            // step3 创建数据模型
            Map<String, Object> dataMap = new HashMap<>(5);
            dataMap.put("char","#");
            dataMap.put("tableName", "s_summary");
            dataMap.put("entityName", "Summary");
            dataMap.put("basePackage", "com.suixingpay.thirdparty");

            dataMap.put("columnList", "id,type,task_no,deploy_date");
/*
            ColumnItem key = new ColumnItem("id","id","VARCHAR","java.lang.String","PRI");
            dataMap.put("key", key);

            List<ColumnItem> columns = new ArrayList<>();
            columns.add(new ColumnItem("id","id","VARCHAR","java.lang.String","PRI"));
            columns.add(new ColumnItem("type","type","VARCHAR","java.lang.String",""));
            columns.add(new ColumnItem("task_no","taskNo","VARCHAR","java.lang.String",""));
            columns.add(new ColumnItem("deploy_date","deployDate","TIMESTAMP","java.util.Date",""));
            dataMap.put("columns", columns);

            List<ColumnItem> normalColumns = new ArrayList<>();
            normalColumns.add(new ColumnItem("id","id","VARCHAR","java.lang.String","PRI"));
            normalColumns.add(new ColumnItem("type","type","VARCHAR","java.lang.String",""));
            normalColumns.add(new ColumnItem("task_no","taskNo","VARCHAR","java.lang.String",""));
            normalColumns.add(new ColumnItem("deploy_date","deployDate","TIMESTAMP","java.util.Date",""));
            dataMap.put("normalColumns", normalColumns);
*/
            // step4 加载模版文件
            Template template = configuration.getTemplate("TEMP_MAPPER.ftl");
            // step5 生成数据
            out = new OutputStreamWriter(os);
            // step6 输出文件
            template.process(dataMap, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != out) {
                    out.flush();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
}
